# 服务端窗口
import wx, time
from socket import socket, AF_INET, SOCK_STREAM
# from threading import Thread
import threading


class ServerWindow(wx.Frame):
    def __init__(self, serverName):

        wx.Frame.__init__(self, None, -1, serverName, size=(400, 600))
        # 创建面板
        panel = wx.Panel(self)
        # 创建盒子
        sizer = wx.BoxSizer(wx.VERTICAL)

        # 伸缩盒子
        flex = wx.FlexGridSizer(1, 3, 5, 5)
        # 按钮
        serve_start = wx.Button(panel, id=wx.ID_ANY, label='启动服务', pos=(0,30), size=(100,50))

        save = wx.Button(panel, id=wx.ID_ANY, label='保留记录', size=(100,50))

        stop = wx.Button(panel, id=wx.ID_ANY, label='停止服务', size=(100,50))

        flex.Add(serve_start, 0, wx.EXPAND, 5)
        flex.Add(save, 0, wx.EXPAND, 5)
        flex.Add(stop, 0, wx.EXPAND, 5)

        sizer.Add(flex, 0, wx.ALIGN_CENTRE, 5)
        panel.SetSizer(sizer)

        self.show_text = wx.TextCtrl(panel, id=wx.ID_ANY, style=wx.TE_MULTILINE|wx.TE_READONLY)
        sizer.Add(self.show_text, 1, wx.EXPAND, 5)

        serve_start.Bind(wx.EVT_BUTTON,self.start_server)
        # self.Bind(wx.EVT_BUTTON,self.start_server,serve_start)
        save.Bind(wx.EVT_BUTTON,self.save_fun)
        stop.Bind(wx.EVT_BUTTON,self.stop_fun)

        self.Show()

        '''---------------以上为ui。以下为事件------------------'''
        # 记录服务启动状态
        self.isOn = False
        # 创建连接
        self.socket_server = socket(AF_INET, SOCK_STREAM)
        # 绑定ip与端口，  ip为空，则表示所有ip都可以接入
        self.socket_server.bind(('', 8890))
        # 监听连接
        self.socket_server.listen(5)
        # 创建字典保存客户端连接的线程对象
        self.session_thread_dict={}

    def start_server(self,event):
        if not self.isOn :
            self.isOn = True
            # 创建线程执行服务启动
            main_thread = threading.Thread(target=self.do_work)
            # 守护线程，父线程执行结束（窗体界面）， 子线程也结束
            main_thread.daemon = True
            # 启动线程
            main_thread.start()

    #  创建服务连接
    def do_work (self) :

        while self.isOn :
            # 等待客端连接,接收客户端信息
            session_socket, childr = self.socket_server.accept()

            # 接收数据
            user_name = session_socket.recv(1024).decode('utf-8')

            session_thread = ThreadChild(session_socket, user_name, self)

            # 把线程与客户端相对应，放入字典中
            self.session_thread_dict[user_name] = session_thread
            # 启动线程
            session_thread.start()

            self.show_info_and_send_client('服务器通知', f'客户端{user_name}进入聊天室', time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))

        self.socket_server.close()

    def show_info_and_send_client (self,data_source, data, dtime) :
        # 组织信息
        send_data = f'{data_source}:{data} \n 发送时间为：{dtime} \n'
        # 放在只读文本框中
        self.show_text.AppendText('---'*40+'\n'+send_data+'\n')

        # 给每个客户端发一份
        for client in self.session_thread_dict.values():
            if client.isOn :
                print(send_data,'-------ison')
                client.client_socket.send(send_data.encode('utf-8'))


    def save_fun(self, event):
        print('保存记录')

    def stop_fun(self, event):
        print('停止服务')

# 创建线程类
class ThreadChild (threading.Thread):
    def __init__(self, client_socket, user_name, server):
        threading.Thread.__init__(self)
        self.client_socket = client_socket
        self.user_name = user_name
        self.server = server
        self.isOn = True #会话线程是否启动

    def run(self) -> None:
        print(f'客户端{self.user_name}已和服务器连接成功,服务启动一个会话线程')
        print('isOn==2222===>',self.isOn)
        while self.isOn :
            print('===1111')
            data = self.client_socket.recv(1024).decode('utf-8')
            print(data,'=======data')
            if data == 'bye':
                self.isOn = False
            else :
                print(self.server.show_info_and_send_client,'--------run')
                self.server.show_info_and_send_client(self.user_name, data, time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))

        self.client_socket.close()

if __name__ == '__main__':
    app = wx.App()
    ServerWindow('服务端窗口')
    app.MainLoop()
